﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import platform
import os
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *
from PySide.QtNetwork import *

_FRAME_WIDTH = 320
_FRAME_HEIGHT = 572
_HEADER_HEIGHT = 43
_FOOTER_HEIGHT = 49
_FOOTER_BUTTON_WIDTH = _FRAME_WIDTH / 3

def factory(type):
	try:
		factory._objects
	except:
		factory._objects = {}
	
	if type is 'MainWindow':		
		if factory._objects.has_key(type):
			return factory._objects[type]
		else:
			factory._objects[type] = MainWindow()
			return factory._objects[type]
	elif type is 'HotkeyMgr':
		if factory._objects.has_key(type):
			return factory._objects[type]
		else:
			factory._objects[type] = HotkeyMgr()
			return factory._objects[type]
	else:
		return None

class HotkeyMgr(QObject):
	evaluateRequested = Signal(str)

	def __init__(self, parent= None):
		super(HotkeyMgr, self).__init__(parent)
		
	@Slot(str,str)
	def append(self, programUrls, keys = ''):
		print '[append] ', programUrls, keys
		
		for programUrl in programUrls:
			program = programUrl.path()
			if platform.system() == 'Windows':
				if program[0] == '/' or program[0] == '\\':
					program = program[1:]
			self.icon(program)
			print program
	
	@Slot()
	def remove(self):
		print '[remove]'
		self.evaluateRequested.emit('$.UI.remove();')
		footer = factory('MainWindow')
		#footer.backBtnClicked()
		
	@Slot(bool,str)
	def removeChecked(self, checked, program):
		footer = factory('MainWindow').getFooter()
		footer.removeChecked(checked)
	
	@Slot()
	def exit(self):
		QCoreApplication.exit(0)		
	
	def icon(self, program):
		fileInfo = QFileInfo(program)
		if fileInfo.isSymLink():
			program = fileInfo.symLinkTarget()
			fileInfo = QFileInfo(program)
				
		iconProvider = QFileIconProvider()
		icon = iconProvider.icon(fileInfo)
		
		# Save the Icon
		pixmap = icon.pixmap(48, 48)
		iconFile = fileInfo.fileName() + '.png'
		pixmap.save(QDir.currentPath() + "/html/icons/" + iconFile, "PNG")
		
		# Insert Icon in HTML
		iconFile = '"' + 'icons/' + iconFile + '"'
		print iconFile
		self.evaluateRequested.emit('$.UI.append(' + iconFile + ', ' + '"' + fileInfo.baseName() + '"' + ');')
	
class WebView(QWebView):
	def __init__(self, parent = None):
		super(WebView, self).__init__(parent)		
		self.loadStarted.connect(self.onStarted)	
		self.loadFinished.connect(self.onFinished)		
		self.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
		self.page().mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
		
		# Create the HotkeyMgr
		#self.hotkeyMgr = HotkeyMgr(self)
		self.hotkeyMgr = factory('HotkeyMgr')
		self.hotkeyMgr.evaluateRequested.connect(self.evaluateJS)		
		
		self.dragPos = QPoint()
		self.dragPos = QPoint()
		
	@Slot()
	def onStarted(self):
		# binding Object to Javascript
		self.page().mainFrame().addToJavaScriptWindowObject("hotkeyMgr", self.hotkeyMgr)
		
	@Slot(bool)
	def onFinished(self, ok):
		pass

	@Slot(str)
	def evaluateJS(self, jsCode):
		print jsCode
		self.page().mainFrame().evaluateJavaScript(jsCode)	

	def dropEvent(self, event):
		programUrls = event.mimeData().urls()
		self.hotkeyMgr.append(programUrls)
		
	def wheelEvent(self, event):
		degrees = event.delta() / 8
		steps = degrees / 15;
		
		if steps > 0:
			self.page().mainFrame().scroll(0, -30)
		else:
			self.page().mainFrame().scroll(0, 30)
		
		#print steps
		print self.page().viewportSize()

class CircleButton(QWidget):
	clicked = Signal()
	
	def __init__(self, fileName, parent = None):
		super(CircleButton, self).__init__(parent)
		self.resize(26, 26)
		
		self.container = QPushButton(self)
		self.container.setFocusPolicy(Qt.NoFocus)
		self.container.clicked.connect(self.clicked)
		self.container.setStyleSheet("QPushButton:pressed { background-color: white; }"
									"QPushButton:hover { background-color: #d9d9d9; }" 
									"QPushButton {width: 26px;"
												"height: 26px;"
												"border-radius: 13px;"
												"background-color: white; }")		
		
		self.button = QPushButton(self.container)
		self.button.setFocusPolicy(Qt.NoFocus)
		self.button.clicked.connect(self.clicked)
		self.button.setStyleSheet("QPushButton:pressed { background-color: #898989; }"
								"QPushButton:hover { background-color: #696969; }" 
								"QPushButton { margin-left: 4px;"
												"margin-top: 4px;"
												"width: 18px;"
												"height: 18px;"
												"border-radius: 9px;"
												"background-color: #898989;"
												"background-image: url(%s); }" % (fileName))
	def enterEvent(self, event):
		QCoreApplication.postEvent(self.button, QEvent(QEvent.Enter))

	def leaveEvent(self, event):
		QCoreApplication.postEvent(self.button, QEvent(QEvent.Leave))

	def leaveEvent(self, event):
		QCoreApplication.postEvent(self.button, QEvent(QEvent.Leave))	
		
class Header(QFrame):
	leftBtnClicked = Signal()
	rightBtnClicked = Signal()
	
	def __init__(self, parent = None):
		super(Header, self).__init__(parent)				
		self.label = QLabel(self)
		self.label.setText("<center><h3><b>Monkey Hotkey</b></h3></center>")
		self.label.setStyleSheet("color: white;" 
								"background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #969696, stop: 0.08 #5f5f5f, stop: 0.49999 #515151, stop: 0.5 #323232, stop: 0.9 #1c1c1c, stop: 1 #000000)");
		self.label.resize(_FRAME_WIDTH, _HEADER_HEIGHT)
		self.label.installEventFilter(self)
		
		self.leftBtn = CircleButton("html/jquery/images/info-18-white.png", self)
		self.leftBtn.move(10, 8)		
		self.leftBtn.clicked.connect(self.leftBtnClicked)

		self.rightBtn = CircleButton("html/jquery/images/close-18-white.png", self)
		self.rightBtn.move(_FRAME_WIDTH - 26 - 10, 8)
		self.rightBtn.clicked.connect(self.rightBtnClicked)

	def resizeEvent(self, event):
		self.label.resize(event.size().width(), _HEADER_HEIGHT)
		self.rightBtn.move(event.size().width() - 26 - 10, 8)
		
	def eventFilter(self, obj, event):
		if obj == self.label:
			if event.type() == QEvent.MouseMove:
				if event.buttons() & Qt.LeftButton:
					self.parentWidget().move(event.globalPos() - self.dragPos)
					return True
				else:
					return False					
			elif event.type() == QEvent.MouseButtonPress:
				if event.button() is Qt.LeftButton:
					self.dragPos = event.globalPos() - self.parentWidget().frameGeometry().topLeft()	
					return True
				else:
					return False
			
		return QFrame.eventFilter(self, obj, event)

class Footer(QFrame):
	removeBtnClicked = Signal()			# 삭제 페이지 진입 버튼 
	removeItemsBtnClicked = Signal()	# 삭제 페이지 내의 아이템 삭제 버튼
	backBtnClicked = Signal()
	setupBtnClicked = Signal()
	infoBtnClicked = Signal()
	
	def __init__(self, parent = None):
		super(Footer, self).__init__(parent)
		self.checked = 0
		self.btnStyle = """QPushButton:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #D7ECFC, stop: 0.04 #85C9FF, stop: 0.05 #78C3FF, stop: 1 #3C7FB5); } 
						QPushButton {color: white; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #969696, stop: 0.04 #5f5f5f, stop: 0.05 #515151, stop: 1 #2A2A2A);
						border-width: 1px;
						border-color: #2C2C2C;
						border-style: hidden solid;}
						"""	
		self.homeLayout()
	
	def initLayout(self):
		layout = self.layout();
		if layout:
			# Remove the layout's items
			while self.layout().count() > 0:
				item = self.layout().takeAt(0)
				print item
				item.widget().deleteLater()
		else:
			# Create the horizontal layout
			layout = QHBoxLayout()
			layout.setContentsMargins(0, 0, 0, 0)
			layout.setSpacing(0)
		
		return layout
		
	def removeChecked(self, checked):
		if checked:
			self.checked += 1
		else:
			self.checked -= 1
		
		text = '삭제' + ' (%s)' % self.checked
		self.removeItemsBtn.setText(self.trUtf8(text))
		
		style = self.removeItemsBtn.styleSheet()
		
		if self.checked is 0:
			style = style.replace('white', 'gray')
		else:
			style = style.replace('gray', 'white')
			
		self.removeItemsBtn.setStyleSheet(style)
	
	def homeLayout(self):
		layout = self.initLayout();
		
		# Create buttons
		self.removeBtn = QPushButton(self.trUtf8('삭제'), self)
		self.removeBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.removeBtn.setFocusPolicy(Qt.NoFocus)
		self.removeBtn.setStyleSheet(self.btnStyle)
		self.removeBtn.clicked.connect(self.removeBtnClicked)
		
		self.setupBtn = QPushButton(self.trUtf8('설정'), self)
		self.setupBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.setupBtn.setFocusPolicy(Qt.NoFocus)
		self.setupBtn.setStyleSheet(self.btnStyle)
		self.setupBtn.clicked.connect(self.setupBtnClicked)
		
		self.infoBtn = QPushButton(self.trUtf8('정보'), self)
		self.infoBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.infoBtn.setFocusPolicy(Qt.NoFocus)
		self.infoBtn.setStyleSheet(self.btnStyle)
		self.infoBtn.clicked.connect(self.infoBtnClicked)		
		
		# Add Layout
		layout.addWidget(self.removeBtn)
		layout.addWidget(self.setupBtn)
		layout.addWidget(self.infoBtn)

		self.setLayout(layout)
		
	def backLayout(self):		
		layout = self.initLayout();
		
		# Create buttons
		self.backBtn = QPushButton(self.trUtf8('이전'), self)
		self.backBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.backBtn.setFocusPolicy(Qt.NoFocus)
		self.backBtn.setStyleSheet(self.btnStyle)
		self.backBtn.clicked.connect(self.backBtnClicked)
		
		# Add Layout
		layout.addWidget(self.backBtn)

		self.setLayout(layout)
	
	def deleteLayout(self):
		layout = self.initLayout();
		self.checked = 0
		
		# Create buttons
		btnStyle = """QPushButton:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #D7ECFC, stop: 0.04 #85C9FF, stop: 0.05 #78C3FF, stop: 1 #3C7FB5); } 
					QPushButton {color: gray; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #969696, stop: 0.04 #5f5f5f, stop: 0.05 #515151, stop: 1 #2A2A2A);
					border-width: 1px;
					border-color: #2C2C2C;
					border-style: hidden solid;}
					"""
		self.removeItemsBtn = QPushButton(self.trUtf8('삭제'), self)
		self.removeItemsBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.removeItemsBtn.setFocusPolicy(Qt.NoFocus)
		self.removeItemsBtn.setStyleSheet(btnStyle)
		self.removeItemsBtn.clicked.connect(self.removeItemsBtnClicked)
		
		self.backBtn = QPushButton(self.trUtf8('이전'), self)
		self.backBtn.setMinimumHeight(_FOOTER_HEIGHT)
		self.backBtn.setFocusPolicy(Qt.NoFocus)
		self.backBtn.setStyleSheet(self.btnStyle)
		self.backBtn.clicked.connect(self.backBtnClicked)
		
		# Add Layout
		layout.addWidget(self.removeItemsBtn)
		layout.addWidget(self.backBtn)

		self.setLayout(layout)

class MainWindow(QDialog):
	def __init__(self, parent = None):
		super(MainWindow, self).__init__(parent)
		
		self.resize(_FRAME_WIDTH, _FRAME_HEIGHT)
		self.setMinimumSize(_FRAME_WIDTH,_FRAME_HEIGHT)
		self.setWindowFlags(Qt.CustomizeWindowHint)
		
		self.webView = WebView(self)
		self.webView.load(QUrl('file:///' + QDir.currentPath() + '/html/ui.html'))		
		
		self.header = Header(self)
		self.header.setMinimumSize(_FRAME_WIDTH, _HEADER_HEIGHT)
		self.header.setMaximumHeight(_HEADER_HEIGHT)
		self.header.leftBtnClicked.connect(self.leftBtnClicked)
		self.header.rightBtnClicked.connect(self.rightBtnClicked)
		
		self.footer = Footer(self)
		self.footer.setMinimumSize(_FRAME_WIDTH, _FOOTER_HEIGHT)
		self.footer.setMaximumHeight(_FOOTER_HEIGHT)
		self.footer.removeBtnClicked.connect(self.removeBtnClicked)
		self.footer.removeItemsBtnClicked.connect(self.removeItemsBtnClicked)
		self.footer.backBtnClicked.connect(self.backBtnClicked)
		self.footer.setupBtnClicked.connect(self.setupBtnClicked)
		self.footer.infoBtnClicked.connect(self.infoBtnClicked)		
		
		self.layout = QVBoxLayout()
		self.layout.setContentsMargins(0, 0, 0, 0)
		self.layout.setSpacing(0)		
		
		self.layout.addWidget(self.header)
		self.layout.addWidget(self.webView)
		self.layout.addWidget(self.footer)
		
		self.setLayout(self.layout)		
	
	def getFooter(self):
		return self.footer
		
	@Slot()
	def leftBtnClicked(self):
		self.webView.evaluateJS('$.UI.showHelp()')
	
	@Slot()	
	def rightBtnClicked(self):
		QCoreApplication.quit()
		
	@Slot()
	def removeBtnClicked(self):
		self.webView.evaluateJS('$.UI.loadRemoveLayer()')
		self.footer.deleteLayout()

	@Slot()
	def removeItemsBtnClicked(self):
		hotkeyMgr = factory('HotkeyMgr')
		hotkeyMgr.remove()
		
	@Slot()
	def backBtnClicked(self):
		self.webView.evaluateJS('$.UI.back()')
		self.footer.homeLayout()
		
	@Slot()
	def setupBtnClicked(self):
		pass

	@Slot()
	def infoBtnClicked(self):
		pass
		
if __name__ == '__main__':
	# Create the Qt application
	app = QApplication(sys.argv)
	
	# Create the MainWindow and show
	frame = factory('MainWindow')
	frame.setWindowTitle('monkeyhotkey-1.1.0')
	frame.show()
	
	# Run the main Qt loop
	sys.exit(app.exec_())
